#include "hittable.h"

bool translate::hit(const ray& r, interval ray_t, hit_record& rec) const
{
	// Move the ray backwards by the offset
	ray offset_r(r.origin() - offset, r.direction(), r.time());// 转化到模型空间

	// Determine whether an intersection exists along the offset ray (and if so, where)
	if (!object->hit(offset_r, ray_t, rec))// 判断是否相交
		return false;

	// Move the intersection point forwards by the offset
	rec.p += offset;// 将交点转化到世界空间

	return true;
}

rotate_y::rotate_y(std::shared_ptr<hittable> object, double angle) : object(object) 
{
	auto radians = degrees_to_radians(angle);
	sin_theta = std::sin(radians);
	cos_theta = std::cos(radians);
	bbox = object->bounding_box();

	point3 min(infinity, infinity, infinity);
	point3 max(-infinity, -infinity, -infinity);

	// 循环遍历包围盒的每个顶点，对其进行旋转，得到新的顶点，然后重新计算包围盒
	for (int i = 0; i < 2; i++) {
		for (int j = 0; j < 2; j++) {
			for (int k = 0; k < 2; k++) {
				auto x = i * bbox.x.max + (1 - i) * bbox.x.min;
				auto y = j * bbox.y.max + (1 - j) * bbox.y.min;
				auto z = k * bbox.z.max + (1 - k) * bbox.z.min;

				auto newx = cos_theta * x + sin_theta * z;
				auto newz = -sin_theta * x + cos_theta * z;

				vec3 tester(newx, y, newz);

				for (int c = 0; c < 3; c++) {
					min[c] = std::fmin(min[c], tester[c]);
					max[c] = std::fmax(max[c], tester[c]);
				}
			}
		}
	}

	bbox = aabb(min, max);
}

bool rotate_y::hit(const ray& r, interval ray_t, hit_record& rec) const
{

	// Transform the ray from world space to object space.

	auto origin = point3(
		(cos_theta * r.origin().x()) - (sin_theta * r.origin().z()),
		r.origin().y(),
		(sin_theta * r.origin().x()) + (cos_theta * r.origin().z())
	);// 将光线原点变换到对象空间

	auto direction = vec3(
		(cos_theta * r.direction().x()) - (sin_theta * r.direction().z()),
		r.direction().y(),
		(sin_theta * r.direction().x()) + (cos_theta * r.direction().z())
	);// 将光线方向变换到对象空间

	ray rotated_r(origin, direction, r.time());

	// Determine whether an intersection exists in object space (and if so, where).

	if (!object->hit(rotated_r, ray_t, rec))// 判断光线是否与物体相交
		return false;

	// Transform the intersection from object space back to world space.

	rec.p = point3(
		(cos_theta * rec.p.x()) + (sin_theta * rec.p.z()),
		rec.p.y(),
		(-sin_theta * rec.p.x()) + (cos_theta * rec.p.z())
	);// 将物体空间中的交点变换回世界空间

	rec.normal = vec3(
		(cos_theta * rec.normal.x()) + (sin_theta * rec.normal.z()),
		rec.normal.y(),
		(-sin_theta * rec.normal.x()) + (cos_theta * rec.normal.z())
	);// 将物体空间中的法线变换回世界空间

	return true;
}

